﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CoreLib.MySQL.Mapping;
using MySql.Data.MySqlClient;
using System.Reflection;

namespace CoreLib.MySQL
{
    public class DbTableCreator : DbBaseQuery<DbTableCreator>, IDbQuery
    {
        private DbProvider dbProvider;
        private List<string> columnsCollection;
        private StringBuilder query;
        private Type classType;
        private string TableName { get; set; }
        private string PrimaryKey { get; set; }
        private int AutoIncrementerStart { get; set; }

        public DbTableCreator(DbProvider dbProvider)
        {
            base.TQuery = this;
            this.dbProvider = dbProvider;
            this.columnsCollection = new List<string>();
            this.query = new StringBuilder();
        }

        public void SourceClass<T>()
        {
            classType = typeof(T);
        }

        public void SourceClassType(Type type)
        {
            classType = type;
        }

        public void Execute()
        {
            CreateTableHeader();
            CreateTableContent();
            this.query = new StringBuilder("Create Table If Not Exists ");
            this.query.Append(this.TableName);
            this.query.Append(" (");
            this.query.Append(string.Join(",", this.columnsCollection));
            if (this.PrimaryKey != null)
            {
                this.query.Append(", PRIMARY KEY ");
                this.query.AppendFormat("(`{0}`)", this.PrimaryKey);
            }

            this.query.Append(")");
            if (this.AutoIncrementerStart != int.MaxValue)
            {
                this.query.Append(" AUTO_INCREMENT = ").Append(this.AutoIncrementerStart);
                this.query.Append(",ENGINE=InnoDB;");
            }
            else
            {
                this.query.Append("ENGINE=InnoDB");
            }

            using (MySqlCommand cmd = new MySqlCommand(this.query.ToString()))
            {
                using (cmd.Connection = dbProvider.CreateDbConnection())
                {
                    cmd.ExecuteNonQuery();
                }
            }
            columnsCollection.Clear();
            query.Clear();
        }

        private void CreateTableHeader()
        {
            foreach (object atr in classType.GetCustomAttributes(true))
            {
                DbTableAttribute attribute = atr as DbTableAttribute;
                if (attribute != null)
                {
                    this.TableName = attribute.TableName;
                    this.AutoIncrementerStart = attribute.AutoIncrementerStart;
                }
            }
        }

        private void CreateTableContent()
        {
            List<DbFieldAttribute> dbFields = DbMap.GetMap(classType);
            foreach (var dbField in dbFields)
            {
                if (dbField.IsPrimaryKey)
                    this.PrimaryKey = dbField.ColumnName;
                PropertyInfo property = dbField.memberInClass as PropertyInfo;
                if(property != null)
                {
                    dbField.VariableType = property.PropertyType;
                }
                else
                {
                    FieldInfo field = dbField.memberInClass as FieldInfo;
                    if (field != null)
                    {
                        dbField.VariableType = field.FieldType;
                    }
                }
                this.columnsCollection.Add(dbField.ToString());
            }
        }
    }
}
